<?php

if( ! defined('DOCROOT') )
{
    require_once '/var/www/advancelab/chilik2/unittest/bootstrap.php';
}

class RegexpRouterTest extends UnitTestCase
{
    function testingMatchEmpty()
    {
        $request = new Core\MVCRequest;
        $request->uri = '';
        
        $route = new Implementation\RegexpRouter( '@^$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array(), $request->variables );
    }
    
    function testingNoMatchEmpty()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'notEmpty';
        
        $route = new Implementation\RegexpRouter( '@^$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( NULL, $routeInfo );
    }
    
    function testingMatchEmptyDefaultVars()
    {
        $request = new Core\MVCRequest;
        $request->uri = '';
        
        $route = new Implementation\RegexpRouter( '@^$@', 'testController', 'action', array('default1' => 'Reality is merely an illusion, albeit a very persistent one.') );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( 'action', $routeInfo->action );
        $this->assertEqual( array('default1' => 'Reality is merely an illusion, albeit a very persistent one.'), $request->variables );
    }
    
    function testingMatchNonEmptyNoVars()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'people/einstein';
        
        $route = new Implementation\RegexpRouter( '@^people/(.*)$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array(), $request->variables );
    }
    
    function testingMatchNonEmptyDefaultVars()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'people/einstein';
        
        $route = new Implementation\RegexpRouter( '@^people/(.*)$@', 'testController', 'action', array('name' => 'chilik') );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('name' => 'chilik'), $request->variables );
    }
    
    function testingMatchNonEmptyOneVar()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'people/einstein';
        
        $route = new Implementation\RegexpRouter( '@^people/(?P<name>.*)$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('name' => 'einstein'), $request->variables );
    }
    
    function testingMatchNonEmptyDefaultVarReused()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'people/einstein';
        
        $route = new Implementation\RegexpRouter( '@^people/(?P<name>.*)$@', 'testController', 'action', array('name' => 'chilik') );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('name' => 'einstein'), $request->variables );
    }
    
    function testingMatchNonEmptyTwoVar()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'people/newton';
        
        $route = new Implementation\RegexpRouter( '@^(?P<group>people)/(?P<name>.*)$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('group' => 'people','name' => 'newton'), $request->variables );
    }
    
    function testingNoMatchNonEmptyTwoVar()
    {
        $request = new Core\MVCRequest;
        $request->uri = 'folks/newton';
        
        $route = new Implementation\RegexpRouter( '@^(?P<group>people)/(?P<name>.*)$@', 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( NULL, $routeInfo );
    }
    
    function testingMatchComplex()
    {
        $route = new Implementation\RegexpRouter( '@^people(/((?P<nr>[0-9]+)|(?P<name>.+)))?$@', 'testController', 'action', array('nr' => '', 'name' => '') );
        $request = new Core\MVCRequest;
        $request->uri = 'people/newton';
        
        $routeInfo = $route->matches( $request );
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('nr' => '','name' => 'newton'), $request->variables );
        
        $request = new Core\MVCRequest;
        $request->uri = 'people/42';
        
        $routeInfo = $route->matches( $request );
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('nr' => '42','name' => ''), $request->variables );
        
        $request = new Core\MVCRequest;
        $request->uri = 'people';
        
        $routeInfo = $route->matches( $request );
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('nr' => '','name' => ''), $request->variables );
        
        $request = new Core\MVCRequest;
        $request->uri = 'people/';
        
        $routeInfo = $route->matches( $request );
        $this->assertEqual( NULL, $routeInfo );
    }
    
    public function testingPrefixSameDelims()
    {
        $route = new testRegexpRoute( '@^entry/(?P<id>[0-9]+)@', 'ignored' );
        $route->prefix('@^blog/@');
        
        $this->assertEqual( '@^blog/entry/(?P<id>[0-9]+)@', $route->getPattern() );
    }
    
    public function testingPrefixDifferentDelims()
    {
        $route = new testRegexpRoute( '@^entry/(?P<id>[0-9]+)@', 'ignored' );
        $route->prefix('#^blog/#');
        
        $this->assertEqual( '@^blog/entry/(?P<id>[0-9]+)@', $route->getPattern() );
    }
    
    public function testingPrefixSameDelimsSameSpecifier()
    {
        $route = new testRegexpRoute( '@^entry/(?P<id>[0-9]+)@i', 'ignored' );
        $route->prefix('@^blog/@i');
        
        $this->assertEqual( '@^blog/entry/(?P<id>[0-9]+)@i', $route->getPattern() );
    }
    
    public function testingPrefixDifferentDelimsSameSpecifier()
    {
        $route = new testRegexpRoute( '@^entry/(?P<id>[0-9]+)@i', 'ignored' );
        $route->prefix('#^blog/#i');
        
        $this->assertEqual( '@^blog/entry/(?P<id>[0-9]+)@i', $route->getPattern() );
    }
    
    public function testingPrefixDifferentDelimsDifferentSpecifier()
    {
        $route = new testRegexpRoute( '@^entry/(?P<id>[0-9]+)@', 'ignored' );
        
        try
        {
            $route->prefix('#^blog/#i');
            $this->fail('Expected exception not thrown');
        }
        catch( Exception $e )
        {
            $this->assertEqual( 'The pattern modifiers of the prefix #^blog/#i and pattern @^entry/(?P<id>[0-9]+)@ do not match.', $e->getMessage() );
        }
    }
    
    function testingMatchWithDifferentUriMatch()
    {
        $request = new Core\MVCRequest();
        $request->host = 'test.host';
        $request->uri = '/people/newton';
        $request->requestId = $request->host.$request->uri;
        
        $route = new testRegexpRouterForFullUri( '@^(?P<site>[a-z]+).host/(?P<group>[a-z]+)/(?P<name>[a-z]+)$@' , 'testController' );
        $routeInfo = $route->matches( $request );
        
        $this->assertEqual( '@^(?P<site>[a-z]+).host/(?P<group>[a-z]+)/(?P<name>[a-z]+)$@', $routeInfo->matchedRoute );
        $this->assertEqual( 'testController', $routeInfo->controllerClass );
        $this->assertEqual( array('site' => 'test', 'group' => 'people', 'name' => 'newton'), $request->variables );
        
        
    }
    
    function testingGenerateUrl()
    {
        $patterns = array(
            '@(?P<arg1>.*)@',
            '@/bar/(?P<arg1>[^/]*)/test/$@',
            '@^/bar/(?P<arg1>[^/]*)/test/@',
            '@^/bar/(?P<arg1>[^/]*)/test/$@',
            '@/bar/(?P<arg1>[^/]*)/test/@',
            '@/bar/(?P<arg1>(foo|bar)[^/]*)/test/@',
            '@/bar/(?P<arg1>[^/]*)/(?P<arg2>[^/]*)/@',
        );
        
        $expecteds = array(
            'val1',
            '/bar/val1/test/',
            '/bar/val1/test/',
            '/bar/val1/test/',
            '/bar/val1/test/',
            '/bar/val1/test/',
            '/bar/val1/val2/',
        );
        
        foreach($patterns as $key => $pattern)
        {
            $fixture = new Implementation\RegexpRouter( $pattern, 'testController' );
            $result = $fixture->generateUrl( array('arg1' => 'val1', 'arg2' => 'val2') );
            $this->assertEqual( $expecteds[$key], $result );
        }
        
    }
}
